#include <gtest/gtest.h>
#include "Poller/EventPoller.h"
#include <chrono>
#include <atomic>
#include <thread>
#include <future>

#ifdef _WIN32
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
#else
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif

using namespace toolkit;
using namespace std::chrono_literals;

// 创建一对套接字
std::pair<int, int> createSocketPair() {
#ifdef _WIN32
    // Windows下创建一对TCP套接字
    SOCKET listener = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    addr.sin_port = 0;
    bind(listener, (struct sockaddr*)&addr, sizeof(addr));
    listen(listener, 1);
    
    int len = sizeof(addr);
    getsockname(listener, (struct sockaddr*)&addr, &len);
    
    SOCKET client = socket(AF_INET, SOCK_STREAM, 0);
    connect(client, (struct sockaddr*)&addr, sizeof(addr));
    
    SOCKET server = accept(listener, NULL, NULL);
    closesocket(listener);
    
    return {(int)client, (int)server};
#else
    // Unix下使用socketpair
    int fds[2];
    socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
    return {fds[0], fds[1]};
#endif
}

// 关闭套接字
void closeSocket(int fd) {
#ifdef _WIN32
    closesocket(fd);
#else
    close(fd);
#endif
}

// 测试基本功能
TEST(EventPollerTest, BasicFunctionality) {
    // 初始化套接字库
#ifdef _WIN32
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif

    auto poller = std::make_shared<EventPoller>("test");
    
    // 启动事件循环
    std::thread loop_thread([poller]() {
        poller->runLoop();
    });
    
    // 等待事件循环启动
    std::this_thread::sleep_for(100ms);
    
    // 测试异步任务
    std::atomic<bool> task_executed{false};
    poller->async([&task_executed]() {
        task_executed = true;
    });
    
    // 等待任务执行
    std::this_thread::sleep_for(100ms);
    EXPECT_TRUE(task_executed);
    
    // 关闭事件循环
    poller->shutdown();
    loop_thread.join();
    
#ifdef _WIN32
    WSACleanup();
#endif
}

// 测试事件监听
TEST(EventPollerTest, EventListening) {
    // 初始化套接字库
#ifdef _WIN32
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif

    auto poller = std::make_shared<EventPoller>("test");
    
    // 创建一对套接字
    auto [fd1, fd2] = createSocketPair();
    
    // 启动事件循环
    std::thread loop_thread([poller]() {
        poller->runLoop();
    });
    
    // 等待事件循环启动
    std::this_thread::sleep_for(100ms);
    
    // 监听读事件
    std::atomic<bool> read_event_triggered{false};
    poller->addEvent(fd1, PollEvent::READ, [&read_event_triggered](int event) {
        if ((event & static_cast<int>(PollEvent::READ)) != 0) {
            read_event_triggered = true;
            
            // 读取数据
            char buf[128];
#ifdef _WIN32
            recv(event, buf, sizeof(buf), 0);
#else
            read(event, buf, sizeof(buf));
#endif
        }
    });
    
    // 发送数据触发读事件
    const char* test_data = "hello";
#ifdef _WIN32
    send(fd2, test_data, strlen(test_data), 0);
#else
    write(fd2, test_data, strlen(test_data));
#endif
    
    // 等待事件触发
    std::this_thread::sleep_for(100ms);
    EXPECT_TRUE(read_event_triggered);
    
    // 删除事件监听
    poller->delEvent(fd1);
    
    // 关闭事件循环
    poller->shutdown();
    loop_thread.join();
    
    // 关闭套接字
    closeSocket(fd1);
    closeSocket(fd2);
    
#ifdef _WIN32
    WSACleanup();
#endif
}

// 测试修改事件
TEST(EventPollerTest, ModifyEvent) {
    // 初始化套接字库
#ifdef _WIN32
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif

    auto poller = std::make_shared<EventPoller>("test");
    
    // 创建一对套接字
    auto [fd1, fd2] = createSocketPair();
    
    // 启动事件循环
    std::thread loop_thread([poller]() {
        poller->runLoop();
    });
    
    // 等待事件循环启动
    std::this_thread::sleep_for(100ms);
    
    // 监听读事件
    std::atomic<bool> read_event_triggered{false};
    std::atomic<bool> write_event_triggered{false};
    
    poller->addEvent(fd1, PollEvent::READ, [&](int event) {
        if ((event & static_cast<int>(PollEvent::READ)) != 0) {
            read_event_triggered = true;
            
            // 读取数据
            char buf[128];
#ifdef _WIN32
            recv(event, buf, sizeof(buf), 0);
#else
            read(event, buf, sizeof(buf));
#endif
        }
        if ((event & static_cast<int>(PollEvent::WRITE)) != 0) {
            write_event_triggered = true;
        }
    });
    
    // 发送数据触发读事件
    const char* test_data = "hello";
#ifdef _WIN32
    send(fd2, test_data, strlen(test_data), 0);
#else
    write(fd2, test_data, strlen(test_data));
#endif
    
    // 等待事件触发
    std::this_thread::sleep_for(100ms);
    EXPECT_TRUE(read_event_triggered);
    EXPECT_FALSE(write_event_triggered);
    
    // 修改为读写事件
    poller->modifyEvent(fd1, PollEvent::READ | PollEvent::WRITE);
    
    // 重置标志
    read_event_triggered = false;
    
    // 再次发送数据
#ifdef _WIN32
    send(fd2, test_data, strlen(test_data), 0);
#else
    write(fd2, test_data, strlen(test_data));
#endif
    
    // 等待事件触发
    std::this_thread::sleep_for(100ms);
    EXPECT_TRUE(read_event_triggered);
    EXPECT_TRUE(write_event_triggered);
    
    // 删除事件监听
    poller->delEvent(fd1);
    
    // 关闭事件循环
    poller->shutdown();
    loop_thread.join();
    
    // 关闭套接字
    closeSocket(fd1);
    closeSocket(fd2);
    
#ifdef _WIN32
    WSACleanup();
#endif
}

// 测试异步任务
TEST(EventPollerTest, AsyncTasks) {
    auto poller = std::make_shared<EventPoller>("test");
    
    // 启动事件循环
    std::thread loop_thread([poller]() {
        poller->runLoop();
    });
    
    // 等待事件循环启动
    std::this_thread::sleep_for(100ms);
    
    // 测试普通异步任务
    std::atomic<int> counter{0};
    for (int i = 0; i < 10; i++) {
        poller->async([&counter]() {
            counter++;
        });
    }
    
    // 等待任务执行
    std::this_thread::sleep_for(100ms);
    EXPECT_EQ(counter, 10);
    
    // 测试优先异步任务
    std::vector<int> execution_order;
    std::mutex mutex;
    
    // 提交5个普通任务
    for (int i = 0; i < 5; i++) {
        poller->async([i, &execution_order, &mutex]() {
            std::this_thread::sleep_for(10ms);
            std::lock_guard<std::mutex> lock(mutex);
            execution_order.push_back(i);
        });
    }
    
    // 提交一个优先任务
    poller->async_first([&execution_order, &mutex]() {
        std::lock_guard<std::mutex> lock(mutex);
        execution_order.push_back(999);
    });
    
    // 等待任务执行
    std::this_thread::sleep_for(200ms);
    
    // 检查执行顺序
    std::lock_guard<std::mutex> lock(mutex);
    EXPECT_EQ(execution_order.size(), 6);
    EXPECT_EQ(execution_order[0], 999); // 优先任务应该先执行
    
    // 关闭事件循环
    poller->shutdown();
    loop_thread.join();
}

// 测试任务取消
TEST(EventPollerTest, TaskCancellation) {
    auto poller = std::make_shared<EventPoller>("test");
    
    // 启动事件循环
    std::thread loop_thread([poller]() {
        poller->runLoop();
    });
    
    // 等待事件循环启动
    std::this_thread::sleep_for(100ms);
    
    // 提交一个任务并立即取消
    std::atomic<bool> task_executed{false};
    auto cancelable = poller->async([&task_executed]() {
        task_executed = true;
    });
    
    cancelable->cancel();
    
    // 等待一段时间
    std::this_thread::sleep_for(100ms);
    
    // 任务应该被取消，不会执行
    EXPECT_FALSE(task_executed);
    
    // 关闭事件循环
    poller->shutdown();
    loop_thread.join();
}

// 测试获取当前轮询器
TEST(EventPollerTest, GetCurrentPoller) {
    auto poller = std::make_shared<EventPoller>("test");
    
    // 在非事件循环线程中，应该获取不到当前轮询器
    EXPECT_EQ(EventPoller::getCurrentPoller(), nullptr);
    
    // 启动事件循环
    std::thread loop_thread([poller]() {
        poller->runLoop();
    });
    
    // 等待事件循环启动
    std::this_thread::sleep_for(100ms);
    
    // 在事件循环线程中，应该能获取到当前轮询器
    std::promise<EventPoller::Ptr> promise;
    poller->async([&promise]() {
        promise.set_value(EventPoller::getCurrentPoller());
    });
    
    auto future = promise.get_future();
    auto current_poller = future.get();
    
    EXPECT_NE(current_poller, nullptr);
    
    // 关闭事件循环
    poller->shutdown();
    loop_thread.join();
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}